using IQIGame.Extension;
using IQIGame.Onigao.GameAOT;
using IQIGame.Onigao.GamePlay;
using IQIGame.Rendering;
using Sirenix.OdinInspector;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;

[ExecuteAlways]
[RequireComponent(typeof(BehaviorFeatureComp))]
[RequireComponent(typeof(PlayableDirector))]
public class CharacterToneShading : MonoBehaviour, ICompnentParams
{
    [LabelText("自动记录根节点坐标")]
    public bool WriteWorldPos = true;
    [LabelText("写入SDF世界坐标")]
    public bool WriteSDFMatrix = true;

    OperableCharacter operableCharacter;
    bool renderingToneStandard;

    private void Awake()
    {
        var timeline = gameObject.GetComponent<PlayableDirector>();
        if (timeline != null)
            timeline.playOnAwake = false;
        operableCharacter = GetComponent<OperableCharacter>();
    }

    private void OnEnable()
    {
        renderer = null;
        //游戏启动时默认关闭标准风格化渲染，节约渲染资源
        //需要特写镜头时再开启
        if (Application.isPlaying)
        {
            SetToneStandardEnable(false);
        }
        //编辑状态下默认开启
        else
            SetToneStandardEnable(true);
    }

    private void OnDisable()
    {
        SetToneStandardEnable(false);
    }

    private void OnDestroy()
    {
        mats.Clear();
        materialInstancedCall?.Invoke();
    }

    void Update()
    {
        if (!this.enabled || Materials == null || Materials.Count < 1) return;

        var shadowArea = 0f;
        if (renderingToneStandard)
            shadowArea = ColliderShadow.Instance.GetReceiverCoverArea(gameObject);
        Vector4 worldPosInfo = new Vector4(transform.position.x, transform.position.y, transform.position.z, shadowArea);

        var worldFront = transform.localToWorldMatrix * Vector3.forward;
        var worldRight = transform.localToWorldMatrix * Vector3.right;

        for (int i = 0; i < Materials.Count; i++)
        {
            if (WriteWorldPos)
                Materials[i].SetVector(GameRender.ShaderKeywords.WorldRootCenter, worldPosInfo);

            if (WriteSDFMatrix)
            {
                if (Materials[i].HasProperty(GameRender.ShaderKeywords.SDFFront))
                {
                    var front = Materials[i].GetVector(GameRender.ShaderKeywords.SDFFront);
                    var right = Materials[i].GetVector(GameRender.ShaderKeywords.SDFRight);
                    Materials[i].SetVector(GameRender.ShaderKeywords.SDFFront, new Vector4(worldFront.x, worldFront.y, worldFront.z, front.w));
                    Materials[i].SetVector(GameRender.ShaderKeywords.SDFRight, new Vector4(worldRight.x, worldRight.y, worldRight.z, right.w));
                }
            }
        }
    }

    public void SetParams(string param)
    {
        if (float.TryParse(param, out var radius))
        {
            if (radius > 0.0f)
            {
                var operable = gameObject.GetOrAddComponent<OperableCharacter>();
                operable.Radius = radius;
            }
        }
    }

    //开关标准风格化渲染
    //标准卡通渲染模式默认处于关闭状态，以节约渲染资源，只有在必要时打开
    public void SetToneStandardEnable(bool enable)
    {
        renderingToneStandard = enable;
        if (operableCharacter)
        {
            //角色阴影开关
            //角色会闪烁，暂时关闭阴影效果
            //if (renderingToneStandard)
            //    ColliderShadow.Instance.AddShadowReceiver(gameObject, operableCharacter.GetParams);
            //else
            //    ColliderShadow.Instance.RemoveShadowReceiver(gameObject);
        }

        if (Materials == null || Materials.Count < 1) return;

        for (int i = 0; i < Materials.Count; i++)
        {
            GameRender.SetKeyward(Materials[i], GameRender.StandardToneShading, renderingToneStandard);
        }
    }

#if UNITY_EDITOR
    [Button("开启标准渲染模式")]
    public void OpenStandardShading()
    {
        SetToneStandardEnable(true);
    }
#endif

    #region materils

    new Renderer[] renderer;
    Renderer[] MeshRender
    {
        get
        {
            if (renderer == null || renderer.Length < 1)
                renderer = GetComponentsInChildren<Renderer>();
            return renderer;
        }
    }

    [SerializeField]
    [LabelText("所有子材质")]
    [Space(10)]
    List<Material> mats = new List<Material>();
    Action materialInstancedCall;

    List<Material> Materials
    {
        get
        {
            materialInstancedCall = GameRender.TryFindMaterialsByRenderer(MeshRender, mats, GameRender.ToneShaderTitle);
            return mats;
        }
    }

    #endregion
}
